package org.apache.jmeter.functions;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 随机读取文件中的某一行，并按照分隔符分割
 */
public class RandomValFromFileFunction extends AbstractFunction {

    //自定义function的描述
    private static final List<String> desc = new LinkedList<String>();
    //function名称
    private static final String KEY = "__GetRandomValFromFile";


    /**
     * 线程本地map，尽量读取一次文件后只从map取值
     */
    private static ConcurrentHashMap<String,String> currThreadMap = new ConcurrentHashMap<>();

    /**
     * 是否读完文件的标识
     */
    private static boolean getThreadMapFlag = false;

    static {
        desc.add("参数文件路径");
        desc.add("字段分隔符");
        desc.add("字段占位符");
    }

    /**
     * 参数文件路径
     */
    private CompoundVariable fileAbsPath;
    /**
     * 每行分隔符
     */
    private CompoundVariable fileSplitFlag;
    /**
     * 字段占位符
     */
    private CompoundVariable charPosition;

    /**
     * jmeter插件自定义主方法，在此处处理入参
     * @param sampleResult
     * @param sampler
     * @return
     * @throws InvalidVariableException
     */
    @Override
    public String execute(SampleResult sampleResult, Sampler sampler) throws InvalidVariableException {
        String tempFileAbsPath = String.valueOf(fileAbsPath.execute().trim());
        String tempFileSplitFlag = String.valueOf(fileSplitFlag.execute().trim());
        String tempCharPosition = String.valueOf(charPosition.execute().trim());
        if (!getThreadMapFlag) {
            if (StringUtils.isNoneEmpty(tempFileAbsPath)) {
                LineIterator lineIterator = null;
                try {
                    lineIterator = FileUtils.lineIterator(new File(tempFileAbsPath));
                    int lineFlag = 0;
                    while (lineIterator.hasNext()) {
                        String line = lineIterator.nextLine();
                        currThreadMap.put(String.valueOf(lineFlag),line);
                        lineFlag++;
                    }
                    getThreadMapFlag = true;
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        lineIterator.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

        int size = currThreadMap.size();
        Random random = new Random();
        int anInt = random.nextInt(size);
        String lineStr = currThreadMap.get(String.valueOf(anInt));
        if (StringUtils.isNotEmpty(tempFileSplitFlag)) {
            String[] split = lineStr.split(tempFileSplitFlag);
            if (StringUtils.isNotEmpty(tempCharPosition)) {
                int parseInt = Integer.parseInt(tempCharPosition);
                return split[parseInt];
            } else {
                return lineStr;
            }
        } else {
            return lineStr;
        }

    }

    /**
     * 注入jmeter界面的参数值
     *
     * @param collection
     * @throws InvalidVariableException
     */
    @Override
    public void setParameters(Collection<CompoundVariable> collection) throws InvalidVariableException {
        checkParameterCount(collection, 3);
        Object[] values = collection.toArray();
        fileAbsPath = (CompoundVariable) values[0];
        fileSplitFlag = (CompoundVariable) values[1];
        charPosition = (CompoundVariable) values[2];
    }

    /**
     * 用来定义函数的名称，把自定义的内容显示在函数对话框中
     */
    /**
     * {@inheritDoc}
     */
    @Override
    public String getReferenceKey() {
        return KEY;
    }

    /**
     * 用来设置GUI界面的函数对话框，把自己定义的参数给显示在jmeter的GUI界面上
     */
    /**
     * {@inheritDoc}
     */
    @Override
    public List<String> getArgumentDesc() {
        return desc;
    }

}
